/**
 * 
 */
package org.statewalker.parser.turtle.tokenizer;

import org.statewalker.parser.turtle.TurtleDict1;
import org.statewalker.parser.turtle.tokenizer.NameTokenizer.NameToken;
import org.statewalker.parser.turtle.tokenizer.UriRefTokenizer.UriRefToken;
import org.statewalker.tokenizer.CharStream;
import org.statewalker.tokenizer.ITokenizer;
import org.statewalker.tokenizer.StreamToken;
import org.statewalker.tokenizer.CharStream.Marker;
import org.statewalker.tokenizer.CharStream.Pointer;
import org.statewalker.tokenizer.base.SequenceTokenizer;

/**
 * <pre>
 * [4]  prefixID    ::= '@prefix' ws+ prefixName? ':' uriref
 * </pre>
 * 
 * @author kotelnikov
 */
public class PrefixIdTokenizer implements ITokenizer {
    public static class PrefixIdToken extends StreamToken {

        private NameToken fPrefixNameToken;

        private UriRefToken fUriToken;

        public PrefixIdToken(
            String key,
            boolean open,
            boolean close,
            Pointer begin,
            Pointer end,
            String str) {
            super(key, open, close, begin, end, str);
        }

        public PrefixIdToken(String key, CharStream stream, Marker marker) {
            super(key, stream, marker);
        }

        public PrefixIdToken(String key, Pointer begin, Pointer end, String str) {
            super(key, begin, end, str);
        }

        public NameToken getPrefixNameToken() {
            return fPrefixNameToken;
        }

        public UriRefToken getUriToken() {
            return fUriToken;
        }

        public void setPrefixNameToken(NameToken prefixNameToken) {
            fPrefixNameToken = prefixNameToken;
        }

        public void setUriToken(UriRefToken uriToken) {
            fUriToken = uriToken;
        }

    }

    public final static PrefixIdTokenizer INSTANCE = new PrefixIdTokenizer();

    private String fKey;

    private NameTokenizer fPrefixNameTokenizer;

    private SequenceTokenizer fPrefixTokenizer;

    private WSTokenizer fSpaceTokenizer;

    private UriRefTokenizer fUriTokenizer;

    public PrefixIdTokenizer() {
        this(
            TurtleDict1.PREFIX_ID,
            TurtleDict1._PREFIX_NAME,
            WSTokenizer.INSTANCE,
            UriRefTokenizer.INSTANCE);
    }

    /**
     * 
     */
    public PrefixIdTokenizer(
        String prefixIdKey,
        String prefixNameKey,
        WSTokenizer wsTokenizer,
        UriRefTokenizer uriTokenizer) {
        fPrefixTokenizer = new SequenceTokenizer(prefixIdKey, "@prefix");
        fPrefixNameTokenizer = new NameTokenizer(prefixNameKey) {
            @Override
            protected boolean isExcludedCharacter(char ch) {
                return ch == '_';
            }
        };
        fSpaceTokenizer = wsTokenizer;
        fUriTokenizer = uriTokenizer;
        fKey = prefixIdKey;
    }

    public StreamToken read(CharStream stream) {
        Marker marker = stream.markPosition();
        PrefixIdToken result = null;
        try {
            if (fPrefixTokenizer.read(stream) == null) {
                return null;
            }
            fSpaceTokenizer.read(stream);
            NameToken prefixNameToken = (NameToken) fPrefixNameTokenizer
                .read(stream);
            if (prefixNameToken == null)
                return null;

            fSpaceTokenizer.read(stream);
            if (stream.getChar() != ':')
                return null;
            stream.incPos();
            fSpaceTokenizer.read(stream);

            UriRefToken uriToken = (UriRefToken) fUriTokenizer.read(stream);
            if (uriToken == null)
                return null;
            result = new PrefixIdToken(fKey, stream, marker);
            result.setPrefixNameToken(prefixNameToken);
            result.setUriToken(uriToken);
            return result;
        } finally {
            marker.close(result == null);
        }
    }

}
